package com.jinke.api.modules.ums.controller;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jinke.api.common.api.CommonPage;
import com.jinke.api.common.api.CommonResult;
import com.jinke.api.modules.app.enums.ChannelStatus;
import com.jinke.api.modules.base.request.BasePageListRequest;
import com.jinke.api.modules.ums.model.*;
import com.jinke.api.modules.ums.request.ChannelPageRequest;
import com.jinke.api.modules.ums.request.GetChannelCarrierRequest;
import com.jinke.api.modules.ums.request.GetChannelRequest;
import com.jinke.api.modules.ums.request.GetServiceByChannelIdsRequest;
import com.jinke.api.modules.ums.service.ChannelCarrierService;
import com.jinke.api.modules.ums.service.ChannelPlatformService;
import com.jinke.api.modules.ums.service.ChannelService;
import com.jinke.api.modules.ums.vo.ChannelPageVO;
import com.jinke.api.modules.ums.vo.ChannelTreeVO;
import com.jinke.api.modules.ums.vo.TreeNode;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 后台用户管理
 * Created by macro on 2018/4/26.
 */
@Controller
@Api(tags = "运输服务管理")
@Tag(name = "运输服务管理", description = "运输服务管理")
@RequestMapping("/admin/channel")
public class ChannelController {


    @Resource
    private ChannelPlatformService channelPlatformService;
    @Resource
    private ChannelService channelService;
    @Resource
    private ChannelCarrierService channelCarrierService;

    /**
     * 查询所有平台
     *
     * @param request
     * @return
     */
    @ApiOperation("获取平台")
    @RequestMapping(value = "/channel-platform", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<CommonPage<ChannelPlatform>> getChannelPlatform(@Validated BasePageListRequest request) {
        Page<ChannelPlatform> page = new Page<>(request.getPageNum(), request.getPageSize());
        QueryWrapper<ChannelPlatform> wrapper = new QueryWrapper<>();

        Page<ChannelPlatform> pageResult = channelPlatformService.page(page, wrapper);
        return CommonResult.success(CommonPage.restPage(pageResult));
    }

    @ApiOperation("获取平台货运商")
    @RequestMapping(value = "/channel-carrier", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<CommonPage<ChannelCarrier>> getChannel(@Validated GetChannelCarrierRequest request) {
        Page<ChannelCarrier> page = new Page<>(request.getPageNum(), request.getPageSize());
        LambdaQueryWrapper<ChannelCarrier> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(request.getChannelPlatformId() != null, ChannelCarrier::getChannelPlatformId, request.getChannelPlatformId());
        Page<ChannelCarrier> pageResult = channelCarrierService.page(page, wrapper);
        return CommonResult.success(CommonPage.restPage(pageResult));
    }

    /**
     * 获取所有的货运商
     *getServiceByChannelIds
     * @param
     * @return
     */
    @ApiOperation("获取平台货运商")
    @RequestMapping(value = "/getAllChannel", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<List<ChannelRoot>> getAllChannel() {
        Map<String, List<Integer>> result = channelCarrierService.getAllChannels();

        List<ChannelRoot> channelRoots = new ArrayList<>();

        for (Map.Entry<String, List<Integer>> entry : result.entrySet()) {
            String name = entry.getKey();
            List<Integer> ids = entry.getValue();
            //把自己的货运商id也要保存
            channelRoots.add(new ChannelRoot(ids, name));

        }


        return CommonResult.success(channelRoots);
    }


    /**
     * 查渠道树
     * @return
     */
    @ApiOperation("获取渠道树")
    @RequestMapping(value = "/getChannelThree", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<List<ChannelTreeVO>> getChannelThree() {
        QueryWrapper<ChannelPlatform> wrapper = new QueryWrapper<>();
        List<ChannelTreeVO> channelTreeVOArrayList = new ArrayList<>();
        List<ChannelPlatform> platforms = channelPlatformService.list(wrapper);
        ChannelTreeVO channelTreeVO;
        for (ChannelPlatform platform : platforms) {
            channelTreeVO = new ChannelTreeVO();
            Integer id = platform.getId();
            channelTreeVO.setType("pt");
            channelTreeVO.setTitle(platform.getChannelPlatformName());
            channelTreeVO.setKey(id);
            channelTreeVO.setValue(id);
            channelTreeVO.setId(id);
            channelTreeVO.setLeaf(false);
            channelTreeVOArrayList.add(channelTreeVO);

        }
        QueryWrapper<ChannelCarrier> channelCarrierQueryWrapper = new QueryWrapper<>();

        List<ChannelCarrier> carriers = channelCarrierService.list(channelCarrierQueryWrapper);
       

        QueryWrapper<Channel> channelQueryWrapper = new QueryWrapper<>();
        List<Channel> channels = channelService.list(channelQueryWrapper);
      

        for (ChannelTreeVO treeVO : channelTreeVOArrayList) {
            List<ChannelTreeVO.Sercond> list=new ArrayList<>();
            for (ChannelCarrier carrier : carriers) {

                Integer carrierId = carrier.getId();
                String channelCarrierName = carrier.getChannelCarrierName();
                String channelPlatformId = carrier.getChannelPlatformId();
                if (treeVO.getKey()==(Integer.valueOf(channelPlatformId))) {

                    ChannelTreeVO.Sercond second=new ChannelTreeVO.Sercond();
                    second.setType("carrier");
                    second.setTitle(channelCarrierName);
                    second.setKey(carrierId);
                    second.setId(carrierId);
                    second.setValue(carrierId);
                    second.setLeaf(false);
                    List<ChannelTreeVO.Children> leafChannel=new ArrayList<>();
                    for (Channel channel : channels) {
                        Integer channelId = channel.getId();
                        String channelName = channel.getChannelName();
                        Integer channelCarrierId = channel.getChannelCarrierId();
                        if (carrierId.equals(channelCarrierId)){
                            ChannelTreeVO.Children leaf=new  ChannelTreeVO.Children();
                            BeanUtils.copyProperties(channel,leaf);
                            leaf.setType("channel");
                            leaf.setTitle(channelName );
                            leaf.setKey(channelId);
                            leaf.setId(channelId);
                            leaf.setValue(channelId);
                            leaf.setLeaf(true);
                            leafChannel.add(leaf);
                        }

                    }
                    second.setChildren(leafChannel);
                    list.add(second);
                }

            }
            treeVO.setChildren(list);

        }


        return CommonResult.success(channelTreeVOArrayList);
    }
    /**
     * 查渠道树2 速度没有上面方法快不再继续加type改leaf字段 此方法不用
     * @return
     */
    @ApiOperation("获取渠道树")
    @RequestMapping(value = "/getChannelThree2", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<List<TreeNode>> getChannelThree2() {
        QueryWrapper<ChannelPlatform> wrapper = new QueryWrapper<>();
        List<ChannelTreeVO> channelTreeVOArrayList = new ArrayList<>();
        List<ChannelPlatform> platforms = channelPlatformService.list(wrapper);
        Map<Integer, String> platformTitleMap = platforms.stream().collect(Collectors.toMap(ChannelPlatform::getId, ChannelPlatform::getChannelPlatformName));

        QueryWrapper<ChannelCarrier> channelCarrierQueryWrapper = new QueryWrapper<>();

        List<ChannelCarrier> carriers = channelCarrierService.list(channelCarrierQueryWrapper);
        Map<Integer, String> carrierTitleMap = carriers.stream().collect(Collectors.toMap(ChannelCarrier::getId, ChannelCarrier::getChannelCarrierName));


        QueryWrapper<Channel> channelQueryWrapper = new QueryWrapper<>();
        List<Channel> channels = channelService.list(channelQueryWrapper);

        List<TreeNode> treeNodes = buildTree(channels, carrierTitleMap, platformTitleMap);


        return CommonResult.success(treeNodes);
    }


    public static List<TreeNode> buildTree(List<Channel> channels, Map<Integer, String> carrierTitleMap, Map<Integer, String> platformTitleMap) {
        Map<Integer, TreeNode> platformNodes = new HashMap<>();
        for (Channel channel : channels) {
            Integer platformId = channel.getChannelPlatformId();
            String platformTitle = platformTitleMap.get(platformId);
            TreeNode platformNode;
            if (!platformNodes.containsKey(platformId)) {
                platformNode = new TreeNode(platformId, platformTitle);
                platformNodes.put(platformId, platformNode);
            } else {
                platformNode = platformNodes.get(platformId);
            }

            Integer carrierId = channel.getChannelCarrierId();
            String carrierTitle = carrierTitleMap.get(carrierId);
            TreeNode carrierNode;
            if (!platformNode.getChildren().stream().anyMatch(node -> node.getId().equals(carrierId))) {
                carrierNode = new TreeNode(carrierId, carrierTitle);
                platformNode.getChildren().add(carrierNode);
            } else {
                carrierNode = platformNode.getChildren().stream()
                        .filter(node -> node.getId().equals(carrierId))
                        .findFirst()
                        .orElse(null);
            }

            TreeNode channelNode = new TreeNode(channel.getId(), channel.getChannelName());
            carrierNode.getChildren().add(channelNode);
        }
        return new ArrayList<>(platformNodes.values());
    }



    /**
     * 通过多个渠道id查下级服务
     *
     * @param
     * @return
     */
    @ApiOperation("通过渠道id查下级服务")
    @RequestMapping(value = "/getServiceByChannelIds", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<Map<String, List<ChannelVO>>> getServiceByChannelIds(@Validated GetServiceByChannelIdsRequest idsRequest ) {
        List<CarrierRoot> channelRoots = new ArrayList<>();
        List<Channel> result = channelService.getServiceByChannelIds(idsRequest.getIds());

        //把对应的平台id转成平台名
        Set<Integer> channelPlatformIds = result
                .stream()
                .map(Channel::getChannelPlatformId)
                .collect(Collectors.toSet());
        Map<Integer, String> channelPlatformMap = channelPlatformService.list(new LambdaQueryWrapper<ChannelPlatform>()
                .in(ChannelPlatform::getId, channelPlatformIds))
                .stream().collect(Collectors.toMap(ChannelPlatform::getId, ChannelPlatform::getChannelPlatformName));
        //把结果 转成VO
        List<ChannelVO> channelVOS=new ArrayList<>();
        for (Channel channel : result) {
            String channelPlatformName = channelPlatformMap.get(channel.getChannelPlatformId());
            ChannelVO vo = new ChannelVO(channelPlatformName);


//            channel.getId(),
//                    channel.getChannelName(),
//                    channel.getServiceCode(),
//                    channel.getChannelPlatformId(),
//                    channelPlatformName
            BeanUtils.copyProperties(channel,vo );
            channelVOS.add(vo);
        }
        //按新字段serviceCode分组
        Map<String, List<ChannelVO>> groupedChannels = channelVOS.stream()
                .collect(Collectors.groupingBy(ChannelVO::getServiceCode));

        return CommonResult.success(groupedChannels);
    }


    /**
     * 转成别的
     * @param channels
     * @return
     */
    public static List<ChannelVO> convertChannels(List<Channel> channels) {
        List<ChannelVO> result = new ArrayList<>();

        return result;
    }

    /**
     * 获取平台名
     * @param groupedChannels
     * @param channelPlatformMap
     */
    public static void assignChannelPlatformNames(Map<String, List<ChannelVO>> groupedChannels, Map<Integer, String> channelPlatformMap) {
        groupedChannels.forEach((groupKey, channels) -> {
            for (ChannelVO channel : channels) {
                int id = channel.getChannelPlatformId();
                if (channelPlatformMap.containsKey(id)) {
                    String name = channelPlatformMap.get(id);
                    channel.setChannelPlatformName(name);
                }
            }
        });
    }

    @ApiOperation("获取平台运输服务")
    @RequestMapping(value = "/channel", method = RequestMethod.GET)
    @ResponseBody
    // 缓存到redis 先按pageNum pageSize channelPlatformId channelCarrierId 缓存 每次四个变更都会先取数据库再做缓存
    // 缓存值包裹CommonResult会报异常 在impl里 使用Cacheable
    //@Cacheable(cacheNames = "channelPageByPlatformIdCarrierId", key = "#request.channelPlatformId + ':' + #request.channelCarrierId + ':' + #request.pageNum + ':' + #request.pageSize")
    public CommonResult<CommonPage<Channel>> channel(GetChannelRequest request) {
        Page<Channel> pageResult = channelService.pageList(request);
        return CommonResult.success(CommonPage.restPage(pageResult));
    }


    @ApiOperation("根据ID删除")
    @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST)
    @ResponseBody
    // 清空所有channelPageByPlatformIdCarrierId缓存
    @CacheEvict(cacheNames = "channelPageByPlatformIdCarrierId", allEntries = true)
    public CommonResult delete(@PathVariable Integer id) {
        boolean success = channelService.removeById(id);
        if (success) {
            return CommonResult.success(null);
        } else {
            return CommonResult.failed();
        }
    }

    @ApiOperation("启用/禁用")
    @RequestMapping(value = "/enable/{id}", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult enable(@PathVariable Integer id) {
        Channel channel = channelService.getById(id);
        if (channel == null) {
            return CommonResult.failed();
        }

        ChannelStatus status = channel.getStatus();
        ChannelStatus newStatus = ChannelStatus.ON.equals(status) ? ChannelStatus.OFF : ChannelStatus.ON;
        channel.setStatus(newStatus);
        channelService.updateById(channel);

        return CommonResult.success();
    }

    @ApiOperation("修改运输服务")
    @RequestMapping(value = "/update/{id}", method = RequestMethod.POST)
    @ResponseBody
    // 清空所有channelPageByPlatformIdCarrierId缓存
    @CacheEvict(cacheNames = "channelPageByPlatformIdCarrierId", allEntries = true)
    public CommonResult update(@PathVariable Integer id,
                               @RequestBody Channel channel) {
        channel.setId(id);
        boolean success = channelService.updateById(channel);
        if (success) {
            return CommonResult.success(null);
        } else {
            return CommonResult.failed();
        }
    }

    @ApiOperation("添加运输服务")
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    // 清空所有channelPageByPlatformIdCarrierId缓存
    @CacheEvict(cacheNames = "channelPageByPlatformIdCarrierId", allEntries = true)
    public CommonResult create(@RequestBody Channel channel) {
        if (StringUtils.isBlank(channel.getServiceCode())){
            //原来新增时没有分组
            channel.setServiceCode("其它");
        }

        boolean success = channelService.save(channel);
        if (success) {
            return CommonResult.success(null);
        } else {
            return CommonResult.failed();
        }
    }
    @ApiOperation("新添加运输服务")
    @RequestMapping(value = "/createNew", method = RequestMethod.POST)
    @ResponseBody
    // 清空所有channelPageByPlatformIdCarrierId缓存
    @CacheEvict(cacheNames = "channelPageByPlatformIdCarrierId", allEntries = true)
    public CommonResult createNew(@RequestBody ChannelDTO channelDTO) {
        if (StringUtils.isBlank(channelDTO.getServiceCode())){
            //原来新增时没有分组
            channelDTO.setServiceCode("其它");
        }
        //如果没有货运id 通过channel_carrier选择的三方平台和货运商名确定一个
        if (channelDTO.getChannelCarrierId()==null){
            //原来新增时没有分组
            List<ChannelCarrier> carrierByCarrierNameAndPlatformId = channelCarrierService.getCarrierByCarrierNameAndPlatformId(channelDTO.getCarrierName(), channelDTO.getChannelPlatformId());
            if (CollectionUtils.isNotEmpty(carrierByCarrierNameAndPlatformId)){
                ChannelCarrier channelCarrier = carrierByCarrierNameAndPlatformId.get(0);
                //找一个关联id设置上 如果一个三方只有一个一级货运商 这里就是唯一的
                channelDTO.setChannelCarrierId(channelCarrier.getId());
            }
        }
//复制属性
        Channel channel=new Channel();
        BeanUtils.copyProperties(channelDTO,channel);
        boolean success = channelService.save(channel);
        if (success) {
            return CommonResult.success(null);
        } else {
            return CommonResult.failed();
        }
    }


    /**
     * 渠道列表分页
     * @param request
     * @return
     */
    @ApiOperation("渠道列表")
    @GetMapping("/page")
    @ResponseBody
    public CommonResult<CommonPage<ChannelPageVO>> page(ChannelPageRequest request) {
        Page<Channel> channelPage = Optional.ofNullable(
                channelService.page(
                        new Page<>(request.getPageNum(), request.getPageSize()),
                        Wrappers.<Channel>lambdaQuery()
                                .eq(ObjectUtil.isNotNull(request.getChannelPlatformId()), Channel::getChannelPlatformId, request.getChannelPlatformId())
                                .eq(ObjectUtil.isNotNull(request.getChannelCarrierId()), Channel::getChannelCarrierId, request.getChannelCarrierId())
                                .select(Channel::getChannelId, Channel::getChannelName, Channel::getChannelPlatformId, Channel::getChannelCode,
                                        Channel::getServiceCode, Channel::getChannelCarrierId, Channel::getChannelOriginName, Channel::getRate,
                                        Channel::getPrice, Channel::getIsBest, Channel::getPlatformRate, Channel::getStatus, Channel::getNote,
                                        Channel::getUuid, Channel::getPostCard, Channel::getCreatedAt)
                                .orderByDesc(Channel::getCreatedAt))
        ).orElse(new Page<Channel>());
        return CommonResult.success(CommonPage.restPage(
                new Page<ChannelPageVO>()
                        .setCurrent(channelPage.getCurrent())
                        .setSize(channelPage.getSize())
                        .setTotal(channelPage.getTotal())
                        .setRecords(
                                Optional.ofNullable(channelPage.getRecords()).orElse(Lists.newArrayList())
                                        .stream().map(channel -> {
                                            ChannelPageVO channelPageVO = new ChannelPageVO();
                                            BeanUtils.copyProperties(channel, channelPageVO);
                                            return channelPageVO;
                                        }).collect(Collectors.toList())
                        )
        ));
    }
}